package query.ddl

import ast.statement.ddl.SqlCreateTable
import ast.statement.ddl.SqlCreateTableColumn
import ast.expr.SqlIdentifierExpr
import expr.DB
import query.ReviseQuery
import util.toSqlString
import visitor.getExpr
import java.sql.Connection

class CreateTable(
    var db: DB = DB.MYSQL,
    override var conn: Connection? = null,
    override var isTransaction: Boolean = false
) : ReviseQuery() {
    constructor(db: DB) : this(db, null, false)

    private var sqlCreateTable = SqlCreateTable()

    infix fun create(table: String): CreateTable {
        sqlCreateTable.name = SqlIdentifierExpr(table)
        return this
    }

    infix fun columns(columns: CreateTable.() -> Unit): CreateTable {
        columns()
        return this
    }

    fun add(column: Column): CreateTable {
        val sqlColumn = SqlCreateTableColumn()
        sqlColumn.apply {
            name = SqlIdentifierExpr(column.columnName)
            dataType = column.dataType
            primary = column.isPrimaryKey
            notNull = column.isNotNull
            column.default?.let {
                default = getExpr(it)
            }
        }
        sqlCreateTable.columnList.add(sqlColumn)

        return this
    }

    fun column(columnName: String): Column {
        return Column(columnName = columnName)
    }

    class Column(
        var columnName: String = "",
        var dataType: String = "",
        var isPrimaryKey: Boolean = false,
        var isNotNull: Boolean = false,
        var default: Any? = null
    ) {
        fun dataType(dataType: String): Column {
            this.dataType = dataType
            return this
        }

        fun primaryKey(): Column {
            this.isPrimaryKey = true
            return this
        }

        fun notNull(): Column {
            this.isNotNull = true
            return this
        }

        fun default(value: Any): Column {
            this.default = value
            return this
        }
    }

    override fun sql() = toSqlString(sqlCreateTable, db)
}